package cn.topcode.unicorn.wxsdk.base;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.topcode.unicorn.utils.XmlUtil;
import cn.topcode.unicorn.wxsdk.WXMessageHandler;
import cn.topcode.unicorn.wxsdk.WXMessageListener;
import cn.topcode.unicorn.wxsdk.message.receive.msg.Message;
import cn.topcode.unicorn.wxsdk.message.reply.ReplyMessage;
import cn.topcode.unicorn.wxsdk.message.reply.ReplySuccessMessage;

/**
 * 微信消息中心
 * 监听器：一个消息类型可以绑定多个监听器
 * 处理器：一个消息类型仅能绑定一个处理器，该处理决定最终返回微信服务器的结果
 * @author Unicorn Lien
 * 2017年3月28日 下午10:54:45 创建
 */
public class WXMessageCenter {
    
    private static WXMessageCenter instance = null;
    
    private Map<Class<? extends Message>, WXMessageHandler<? extends Message>> handlers = new HashMap<>();

    private Map<Class<? extends Message>, ArrayList<WXMessageListener<? extends Message>>> listeners = new HashMap<>();
    
    private WXMessageCenter() {
        
    }
    
    public static WXMessageCenter getInstance() {
        if(instance == null) {
            synchronized (WXMessageCenter.class) {
                if(instance == null) {
                    instance = new WXMessageCenter();
                }
            }
        }
        return instance;
    }
    
    public void registHandler(Class<? extends Message> clazz, WXMessageHandler<? extends Message> handler) {
        if(clazz == null || handler == null) {
            throw new IllegalArgumentException("微信消息处理器注册失败！class:" + clazz + ",Handler:" + handler);
        }
        this.handlers.put(clazz, handler);
    }
    
    public void unregistHandler(Class<? extends Message> clazz) {
        if(clazz == null) {
            throw new IllegalArgumentException("微信消息处理器移除失败！class:" + clazz);
        }
        this.handlers.remove(clazz);
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public void publish(Message message, OutputStream out) {
        if(message == null) {
            throw new IllegalArgumentException("发布消息不能为空");
        }
        if(out == null) {
            throw new IllegalArgumentException("输出流不能为空");
        }

        //  通知监听器执行，捕获每个监听器的异常避免相互影响
        List<WXMessageListener<? extends Message>> listenerList = this.listeners.get(message.getClass());
        if(listenerList != null) {
            for(WXMessageListener listener : listenerList) {
                try {
                    listener.onReceive(message);
                }catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        //  执行处理器
        WXMessageHandler handler = handlers.get(message.getClass());
        if(handler == null) {
            return;
        }
        ReplyMessage reply = handler.handle(message);
        if(reply == null) {
            try {
                out.write("".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(reply instanceof ReplySuccessMessage) {
            try {
                out.write("success".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            XmlUtil.toXml(reply, out);
        }
    }

    public void registListener(Class<? extends Message> clazz, WXMessageListener<? extends Message> listener) {
        if(clazz == null || listener == null) {
            throw new IllegalArgumentException("微信消息监听器注册失败！class:" + clazz + ",Listener:" + listener);
        }
        ArrayList<WXMessageListener<? extends Message>> list = this.listeners.get(clazz);
        if(list == null) {
            list = new ArrayList<>();
            this.listeners.put(clazz, list);
        }
        if(!list.contains(listener)) {
            list.add(listener);
        }
    }

    public void unregistListener(Class<? extends Message> clazz, WXMessageListener<? extends Message> listener) {
        if(clazz == null || listener == null) {
            throw new IllegalArgumentException("微信消息监听器移除失败！class:" + clazz + ",Listener:" + listener);
        }
        List<WXMessageListener<? extends Message>> list = this.listeners.get(clazz);
        if(list != null) {
            if(list.contains(listener)) {
                list.remove(listener);
            }
        }
    }

    public void unregistListener(Class<? extends Message> clazz) {
        if(clazz == null) {
            throw new IllegalArgumentException("微信消息监听器移除失败！class:" + clazz);
        }
        this.listeners.remove(clazz);
    }
}
